Rearrange all the scroll-while-dragging-or-selecting code to be different,
authorHavoc Pennington <hp@pobox.com>
Sun, 31 Dec 2000 23:28:57 +0000 (23:28 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Sun, 31 Dec 2000 23:28:57 +0000 (23:28 +0000)
2000-12-31  Havoc Pennington  <hp@pobox.com>

* gtk/gtktextview.c: Rearrange all the
scroll-while-dragging-or-selecting code to be different, not
necessarily better. ;-)
(gtk_text_view_scroll_to_mark): Change this
function to take within_margin as a fraction instead of a pixel
value, and to take alignment arguments (indicating where to align
the mark inside the visible area)

* gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
to GtkObject

* gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
behavior so that offsets past the end of the line are not
allowed, and an offset equal to the line length moves the iterator
to the next line
(gtk_text_iter_set_line_index): make parallel change
(gtk_text_iter_get_bytes_in_line): add this function

* gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
of byte indexes off the end of the line; byte index at the end of
the line now returns FALSE and doesn't fill in the requested
values, byte index past the end of the line is an error.  Also,
don't allow -1 offset anymore, since its meaning is unclear.

This change exposes some bug in visual cursor motion, where we
end up with a huge invalid byte index; needs fixing. Symptom of
bug is a crash when you hit up arrow.

(_gtk_text_line_char_locate): match the change to byte_locate

* gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
from start of line properly. fixes bug reported by Mikael
Hermansson where backspace would delete all text before the
cursor.

15 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktextview.c
gtk/gtktextview.h
gtk/testtextbuffer.c
tests/testtextbuffer.c

index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 182815448a5b203dd356e75930723787ca34b60c..c836c397517463afbaa88501c6f7f3b0a9b5b5bc 100644 (file)
@@ -1,3 +1,40 @@
+2000-12-31  Havoc Pennington  <hp@pobox.com>
+
+       * gtk/gtktextview.c: Rearrange all the
+       scroll-while-dragging-or-selecting code to be different, not
+       necessarily better. ;-)
+       (gtk_text_view_scroll_to_mark): Change this
+       function to take within_margin as a fraction instead of a pixel
+       value, and to take alignment arguments (indicating where to align 
+       the mark inside the visible area)
+       
+       * gtk/testtextbuffer.c (fill_buffer): fix bad cast of GtkTextTag
+       to GtkObject
+
+       * gtk/gtktextiter.c (gtk_text_iter_set_line_offset): change
+       behavior so that offsets past the end of the line are not 
+       allowed, and an offset equal to the line length moves the iterator
+       to the next line
+       (gtk_text_iter_set_line_index): make parallel change
+       (gtk_text_iter_get_bytes_in_line): add this function
+       
+       * gtk/gtktextbtree.c (_gtk_text_line_byte_locate): change handling
+       of byte indexes off the end of the line; byte index at the end of
+       the line now returns FALSE and doesn't fill in the requested
+       values, byte index past the end of the line is an error.  Also,
+       don't allow -1 offset anymore, since its meaning is unclear.
+
+       This change exposes some bug in visual cursor motion, where we
+       end up with a huge invalid byte index; needs fixing. Symptom of 
+       bug is a crash when you hit up arrow.
+       
+       (_gtk_text_line_char_locate): match the change to byte_locate
+
+       * gtk/gtktextiter.c (find_by_log_attrs): Handle iteration backward
+       from start of line properly. fixes bug reported by Mikael
+       Hermansson where backspace would delete all text before the
+       cursor.
+
 2000-12-30  Tor Lillqvist  <tml@iki.fi>
 
        * gdk/win32/gdkwindow-win32.c
index 5bd08b90266111fe31ac308e06f5fc1f470d0356..97ea5ab425c0a7af5a2978b088f6dded169c803d 100644 (file)
@@ -1053,9 +1053,9 @@ _gtk_text_btree_insert (GtkTextIter *iter,
 
 
     _gtk_text_btree_get_iter_at_line (tree,
-                                     &start,
-                                     start_line,
-                                     start_byte_index);
+                                      &start,
+                                      start_line,
+                                      start_byte_index);
     end = start;
 
     /* We could almost certainly be more efficient here
@@ -3545,13 +3545,13 @@ _gtk_text_line_char_to_byte (GtkTextLine *line,
 
 /* FIXME sync with char_locate (or figure out a clean
    way to merge the two functions) */
-void
+gboolean
 _gtk_text_line_byte_locate (GtkTextLine *line,
-                           gint byte_offset,
-                           GtkTextLineSegment **segment,
-                           GtkTextLineSegment **any_segment,
-                           gint *seg_byte_offset,
-                           gint *line_byte_offset)
+                            gint byte_offset,
+                            GtkTextLineSegment **segment,
+                            GtkTextLineSegment **any_segment,
+                            gint *seg_byte_offset,
+                            gint *line_byte_offset)
 {
   GtkTextLineSegment *seg;
   GtkTextLineSegment *after_prev_indexable;
@@ -3560,16 +3560,8 @@ _gtk_text_line_byte_locate (GtkTextLine *line,
   gint offset;
   gint bytes_in_line;
 
-  g_return_if_fail (line != NULL);
-
-  if (byte_offset < 0)
-    {
-      /* -1 means end of line; we here assume no line is
-         longer than 1 bazillion bytes, of course we assumed
-         that anyway since we'd wrap around... */
-
-      byte_offset = G_MAXINT;
-    }
+  g_return_val_if_fail (line != NULL, FALSE);
+  g_return_val_if_fail (byte_offset >= 0, FALSE);
 
   *segment = NULL;
   *any_segment = NULL;
@@ -3602,11 +3594,10 @@ _gtk_text_line_byte_locate (GtkTextLine *line,
   if (seg == NULL)
     {
       /* We went off the end of the line */
-      *segment = last_indexable;
-      *any_segment = after_prev_indexable;
-      /* subtracting 1 is OK, we know it's a newline at the end. */
-      offset = (*segment)->byte_count - 1;
-      bytes_in_line -= (*segment)->byte_count;
+      if (offset != 0)
+        g_warning ("%s: byte index off the end of the line", G_STRLOC);
+
+      return FALSE;
     }
   else
     {
@@ -3628,17 +3619,19 @@ _gtk_text_line_byte_locate (GtkTextLine *line,
   g_assert (*seg_byte_offset < (*segment)->byte_count);
 
   *line_byte_offset = bytes_in_line + *seg_byte_offset;
+
+  return TRUE;
 }
 
 /* FIXME sync with byte_locate (or figure out a clean
    way to merge the two functions) */
-void
+gboolean
 _gtk_text_line_char_locate     (GtkTextLine     *line,
-                               gint              char_offset,
-                               GtkTextLineSegment **segment,
-                               GtkTextLineSegment **any_segment,
-                               gint             *seg_char_offset,
-                               gint             *line_char_offset)
+                                gint              char_offset,
+                                GtkTextLineSegment **segment,
+                                GtkTextLineSegment **any_segment,
+                                gint             *seg_char_offset,
+                                gint             *line_char_offset)
 {
   GtkTextLineSegment *seg;
   GtkTextLineSegment *after_prev_indexable;
@@ -3647,17 +3640,9 @@ _gtk_text_line_char_locate     (GtkTextLine     *line,
   gint offset;
   gint chars_in_line;
 
-  g_return_if_fail (line != NULL);
-
-  if (char_offset < 0)
-    {
-      /* -1 means end of line; we here assume no line is
-         longer than 1 bazillion chars, of course we assumed
-         that anyway since we'd wrap around... */
-
-      char_offset = G_MAXINT;
-    }
-
+  g_return_val_if_fail (line != NULL, FALSE);
+  g_return_val_if_fail (char_offset >= 0, FALSE);
+  
   *segment = NULL;
   *any_segment = NULL;
   chars_in_line = 0;
@@ -3688,12 +3673,11 @@ _gtk_text_line_char_locate     (GtkTextLine     *line,
 
   if (seg == NULL)
     {
-      /* We went off the end of the line */
-      *segment = last_indexable;
-      *any_segment = after_prev_indexable;
-      /* subtracting 1 is OK, we know it's a newline at the end. */
-      offset = (*segment)->char_count - 1;
-      chars_in_line -= (*segment)->char_count;
+      /* end of the line */
+      if (offset != 0)
+        g_warning ("%s: char offset off the end of the line", G_STRLOC);
+
+      return FALSE;
     }
   else
     {
@@ -3715,6 +3699,8 @@ _gtk_text_line_char_locate     (GtkTextLine     *line,
   g_assert (*seg_char_offset < (*segment)->char_count);
 
   *line_char_offset = chars_in_line + *seg_char_offset;
+
+  return TRUE;
 }
 
 void
index 93558fae5cd9408984d47bc904058d6d20138b36..65932b3dc014145e10ff7287edbe61b1dbe374be 100644 (file)
@@ -225,13 +225,13 @@ GtkTextLineSegment *_gtk_text_line_byte_to_segment            (GtkTextLine
 GtkTextLineSegment *_gtk_text_line_char_to_segment            (GtkTextLine         *line,
                                                                gint                 char_offset,
                                                                gint                *seg_offset);
-void                _gtk_text_line_byte_locate                (GtkTextLine         *line,
+gboolean            _gtk_text_line_byte_locate                (GtkTextLine         *line,
                                                                gint                 byte_offset,
                                                                GtkTextLineSegment **segment,
                                                                GtkTextLineSegment **any_segment,
                                                                gint                *seg_byte_offset,
                                                                gint                *line_byte_offset);
-void                _gtk_text_line_char_locate                (GtkTextLine         *line,
+gboolean            _gtk_text_line_char_locate                (GtkTextLine         *line,
                                                                gint                 char_offset,
                                                                GtkTextLineSegment **segment,
                                                                GtkTextLineSegment **any_segment,
index 02bf9443618d5d15fff415c7f1e78fa3d17e22a2..755fc033b2cc98f65c9a141d4d77216ff88eaa27 100644 (file)
@@ -93,12 +93,11 @@ iter_set_from_byte_offset (GtkTextRealIter *iter,
   iter_set_common (iter, line);
 
   _gtk_text_line_byte_locate (iter->line,
-                             byte_offset,
-                             &iter->segment,
-                             &iter->any_segment,
-                             &iter->segment_byte_offset,
-                             &iter->line_byte_offset);
-
+                              byte_offset,
+                              &iter->segment,
+                              &iter->any_segment,
+                              &iter->segment_byte_offset,
+                              &iter->line_byte_offset);
 }
 
 static void
@@ -109,11 +108,11 @@ iter_set_from_char_offset (GtkTextRealIter *iter,
   iter_set_common (iter, line);
 
   _gtk_text_line_char_locate (iter->line,
-                             char_offset,
-                             &iter->segment,
-                             &iter->any_segment,
-                             &iter->segment_char_offset,
-                             &iter->line_char_offset);
+                              char_offset,
+                              &iter->segment,
+                              &iter->any_segment,
+                              &iter->segment_char_offset,
+                              &iter->line_char_offset);
 }
 
 static void
@@ -1289,8 +1288,8 @@ gtk_text_iter_get_language (const GtkTextIter *iter)
  * gtk_text_iter_starts_line:
  * @iter: an iterator
  *
- * Returns TRUE if @iter begins a newline-terminated line,
- * i.e. gtk_text_iter_get_line_offset () would return 0.
+ * Returns TRUE if @iter begins a paragraph,
+ * i.e. if gtk_text_iter_get_line_offset () would return 0.
  * However this function is potentially more efficient than
  * gtk_text_iter_get_line_offset () because it doesn't have to compute
  * the offset, it just has to see whether it's 0.
@@ -1419,7 +1418,7 @@ gtk_text_iter_is_first (const GtkTextIter *iter)
  * @iter: an iterator
  *
  * Returns the number of characters in the line containing @iter,
- * including the terminating newline.
+ * including the paragraph delimiters.
  *
  * Return value: number of characters in the line
  **/
@@ -1463,6 +1462,54 @@ gtk_text_iter_get_chars_in_line (const GtkTextIter   *iter)
   return count;
 }
 
+/**
+ * gtk_text_iter_get_bytes_in_line:
+ * @iter: an iterator
+ *
+ * Returns the number of bytes in the line containing @iter,
+ * including the paragraph delimiters.
+ *
+ * Return value: number of bytes in the line
+ **/
+gint
+gtk_text_iter_get_bytes_in_line (const GtkTextIter   *iter)
+{
+  GtkTextRealIter *real;
+  gint count;
+  GtkTextLineSegment *seg;
+
+  g_return_val_if_fail (iter != NULL, FALSE);
+
+  real = gtk_text_iter_make_surreal (iter);
+
+  if (real == NULL)
+    return 0;
+
+  check_invariants (iter);
+
+  if (real->line_byte_offset >= 0)
+    {
+      /* We can start at the segments we've already found. */
+      count = real->line_byte_offset - real->segment_byte_offset;
+      seg = gtk_text_iter_get_indexable_segment (iter);
+    }
+  else
+    {
+      /* count whole line. */
+      seg = real->line->segments;
+      count = 0;
+    }
+
+  while (seg != NULL)
+    {
+      count += seg->byte_count;
+
+      seg = seg->next;
+    }
+
+  return count;
+}
+
 /**
  * gtk_text_iter_get_attributes:
  * @iter: an iterator
@@ -2388,7 +2435,8 @@ typedef gboolean (* FindLogAttrFunc) (const PangoLogAttr *attrs,
                                       gint                offset,
                                       gint                min_offset,
                                       gint                len,
-                                      gint               *found_offset);
+                                      gint               *found_offset,
+                                      gboolean            already_moved_initially);
 
 typedef gboolean (* TestLogAttrFunc) (const PangoLogAttr *attrs,
                                       gint                offset,
@@ -2400,9 +2448,11 @@ find_word_end_func (const PangoLogAttr *attrs,
                     gint          offset,
                     gint          min_offset,
                     gint          len,
-                    gint         *found_offset)
+                    gint         *found_offset,
+                    gboolean      already_moved_initially)
 {
-  ++offset; /* We always go to the NEXT word end */
+  if (!already_moved_initially)
+    ++offset;
 
   /* Find end of next word */
   while (offset < min_offset + len &&
@@ -2428,9 +2478,11 @@ find_word_start_func (const PangoLogAttr *attrs,
                       gint          offset,
                       gint          min_offset,
                       gint          len,
-                      gint         *found_offset)
+                      gint         *found_offset,
+                      gboolean      already_moved_initially)
 {
-  --offset; /* We always go to the NEXT word start */
+  if (!already_moved_initially)
+    --offset;
 
   /* Find start of prev word */
   while (offset >= min_offset &&
@@ -2469,7 +2521,6 @@ static gboolean
 test_log_attrs (const GtkTextIter *iter,
                 TestLogAttrFunc    func)
 {
-  gchar *paragraph;
   gint char_len;
   const PangoLogAttr *attrs;
   int offset;
@@ -2493,25 +2544,26 @@ test_log_attrs (const GtkTextIter *iter,
 static gboolean
 find_line_log_attrs (const GtkTextIter *iter,
                      FindLogAttrFunc    func,
-                     gint              *found_offset)
+                     gint              *found_offset,
+                     gboolean           already_moved_initially)
 {
-  gchar *paragraph;
   gint char_len;
   const PangoLogAttr *attrs;
   int offset;
   gboolean result = FALSE;
 
   g_return_val_if_fail (iter != NULL, FALSE);
-
+  
   attrs = _gtk_text_buffer_get_line_log_attrs (gtk_text_iter_get_buffer (iter),
-                                               iter, &char_len);
+                                               iter, &char_len);      
 
   offset = gtk_text_iter_get_line_offset (iter);
-
+  
   g_assert (char_len > 0);
   
   if (offset < char_len)
-    result = (* func) (attrs, offset, 0, char_len, found_offset);
+    result = (* func) (attrs, offset, 0, char_len, found_offset,
+                       already_moved_initially);
 
   return result;
 }
@@ -2520,7 +2572,8 @@ find_line_log_attrs (const GtkTextIter *iter,
 static gboolean
 find_by_log_attrs (GtkTextIter    *iter,
                    FindLogAttrFunc func,
-                   gboolean        forward)
+                   gboolean        forward,
+                   gboolean        already_moved_initially)
 {
   GtkTextIter orig;
   gint offset = 0;
@@ -2529,22 +2582,27 @@ find_by_log_attrs (GtkTextIter    *iter,
   g_return_val_if_fail (iter != NULL, FALSE);
 
   orig = *iter;
-
-  found = find_line_log_attrs (iter, func, &offset);
+  
+  found = find_line_log_attrs (iter, func, &offset, already_moved_initially);
   
   if (!found)
     {
       if (forward)
         {
           if (gtk_text_iter_forward_line (iter))
-            return find_by_log_attrs (iter, func, forward);
+            return find_by_log_attrs (iter, func, forward,
+                                      TRUE);
           else
             return FALSE;
         }
       else
-        {
-          if (gtk_text_iter_backward_line (iter))
-            return find_by_log_attrs (iter, func, forward);
+        {                    
+          /* go to end of previous line */
+          gtk_text_iter_set_line_offset (iter, 0);
+          
+          if (gtk_text_iter_backward_char (iter))
+            return find_by_log_attrs (iter, func, forward,
+                                      TRUE);
           else
             return FALSE;
         }
@@ -2562,13 +2620,13 @@ find_by_log_attrs (GtkTextIter    *iter,
 gboolean
 gtk_text_iter_forward_word_end (GtkTextIter *iter)
 {
-  return find_by_log_attrs (iter, find_word_end_func, TRUE);
+  return find_by_log_attrs (iter, find_word_end_func, TRUE, FALSE);
 }
 
 gboolean
 gtk_text_iter_backward_word_start (GtkTextIter      *iter)
 {
-  return find_by_log_attrs (iter, find_word_start_func, FALSE);
+  return find_by_log_attrs (iter, find_word_start_func, FALSE, FALSE);
 }
 
 /* FIXME a loop around a truly slow function means
@@ -2645,9 +2703,11 @@ find_forward_cursor_pos_func (const PangoLogAttr *attrs,
                               gint          offset,
                               gint          min_offset,
                               gint          len,
-                              gint         *found_offset)
+                              gint         *found_offset,
+                              gboolean      already_moved_initially)
 {
-  ++offset; /* We always go to the NEXT position */
+  if (!already_moved_initially)
+    ++offset;
 
   while (offset < (min_offset + len) &&
          !attrs[offset].is_cursor_position)
@@ -2663,16 +2723,18 @@ find_backward_cursor_pos_func (const PangoLogAttr *attrs,
                                gint          offset,
                                gint          min_offset,
                                gint          len,
-                               gint         *found_offset)
+                               gint         *found_offset,
+                               gboolean      already_moved_initially)
 {
-  --offset; /* We always go to the NEXT position */
+  if (!already_moved_initially)
+    --offset;
 
   while (offset > min_offset &&
          !attrs[offset].is_cursor_position)
     --offset;
 
   *found_offset = offset;
-
+  
   return offset >= min_offset;
 }
 
@@ -2688,13 +2750,13 @@ is_cursor_pos_func (const PangoLogAttr *attrs,
 gboolean
 gtk_text_iter_forward_cursor_position (GtkTextIter *iter)
 {
-  return find_by_log_attrs (iter, find_forward_cursor_pos_func, TRUE);
+  return find_by_log_attrs (iter, find_forward_cursor_pos_func, TRUE, FALSE);
 }
 
 gboolean
 gtk_text_iter_backward_cursor_position (GtkTextIter *iter)
 {
-  return find_by_log_attrs (iter, find_backward_cursor_pos_func, FALSE);
+  return find_by_log_attrs (iter, find_backward_cursor_pos_func, FALSE, FALSE);
 }
 
 gboolean
@@ -2755,20 +2817,28 @@ gtk_text_iter_is_cursor_position (const GtkTextIter *iter)
 
 void
 gtk_text_iter_set_line_offset (GtkTextIter *iter,
-                               gint char_on_line)
+                               gint         char_on_line)
 {
   GtkTextRealIter *real;
-
+  gint chars_in_line;
+  
   g_return_if_fail (iter != NULL);
 
   real = gtk_text_iter_make_surreal (iter);
 
   if (real == NULL)
     return;
-
+  
   check_invariants (iter);
 
-  iter_set_from_char_offset (real, real->line, char_on_line);
+  chars_in_line = gtk_text_iter_get_chars_in_line (iter);
+
+  g_return_if_fail (char_on_line <= chars_in_line);
+
+  if (char_on_line < chars_in_line)
+    iter_set_from_char_offset (real, real->line, char_on_line);
+  else
+    gtk_text_iter_forward_line (iter); /* set to start of next line */
 
   check_invariants (iter);
 }
@@ -2778,7 +2848,8 @@ gtk_text_iter_set_line_index (GtkTextIter *iter,
                               gint         byte_on_line)
 {
   GtkTextRealIter *real;
-
+  gint bytes_in_line;
+  
   g_return_if_fail (iter != NULL);
 
   real = gtk_text_iter_make_surreal (iter);
@@ -2788,7 +2859,14 @@ gtk_text_iter_set_line_index (GtkTextIter *iter,
 
   check_invariants (iter);
 
-  iter_set_from_byte_offset (real, real->line, byte_on_line);
+  bytes_in_line = gtk_text_iter_get_bytes_in_line (iter);
+
+  g_return_if_fail (byte_on_line <= bytes_in_line);
+  
+  if (byte_on_line < bytes_in_line)
+    iter_set_from_byte_offset (real, real->line, byte_on_line);
+  else
+    gtk_text_iter_forward_line (iter);
 
   if (real->segment->type == &gtk_text_char_type &&
       (real->segment->body.chars[real->segment_byte_offset] & 0xc0) == 0x80)
@@ -2849,9 +2927,9 @@ gtk_text_iter_set_offset (GtkTextIter *iter, gint char_index)
     return;
 
   line = _gtk_text_btree_get_line_at_char (real->tree,
-                                          char_index,
-                                          &line_start,
-                                          &real_char_index);
+                                           char_index,
+                                           &line_start,
+                                           &real_char_index);
 
   iter_set_from_char_offset (real, line, real_char_index - line_start);
 
@@ -2886,7 +2964,9 @@ gtk_text_iter_forward_to_end  (GtkTextIter       *iter)
  * Moves the iterator to point to the paragraph delimiter characters,
  * which will be either a newline, a carriage return, a carriage
  * return/newline in sequence, or the Unicode paragraph separator
- * character.
+ * character. If the iterator is already at the paragraph delimiter
+ * characters, moves to the paragraph delimiter characters for the
+ * next line.
  * 
  * Return value: %TRUE if we moved and the new location is not the end iterator
  **/
@@ -2899,6 +2979,7 @@ gtk_text_iter_forward_to_delimiters (GtkTextIter *iter)
   g_return_val_if_fail (iter != NULL, FALSE);
 
   current_offset = gtk_text_iter_get_line_offset (iter);
+  /* FIXME assumption that line ends in a newline; broken */
   new_offset = gtk_text_iter_get_chars_in_line (iter) - 1;
 
   if (current_offset < new_offset)
@@ -3955,8 +4036,8 @@ gtk_text_iter_reorder         (GtkTextIter *first,
 
 void
 _gtk_text_btree_get_iter_at_char (GtkTextBTree *tree,
-                                 GtkTextIter *iter,
-                                 gint char_index)
+                                  GtkTextIter *iter,
+                                  gint char_index)
 {
   GtkTextRealIter *real = (GtkTextRealIter*)iter;
   gint real_char_index;
@@ -3978,9 +4059,9 @@ _gtk_text_btree_get_iter_at_char (GtkTextBTree *tree,
 
 void
 _gtk_text_btree_get_iter_at_line_char (GtkTextBTree *tree,
-                                      GtkTextIter *iter,
-                                      gint line_number,
-                                      gint char_on_line)
+                                       GtkTextIter *iter,
+                                       gint line_number,
+                                       gint char_on_line)
 {
   GtkTextRealIter *real = (GtkTextRealIter*)iter;
   GtkTextLine *line;
@@ -3990,7 +4071,7 @@ _gtk_text_btree_get_iter_at_line_char (GtkTextBTree *tree,
   g_return_if_fail (tree != NULL);
 
   line = _gtk_text_btree_get_line (tree, line_number, &real_line);
-
+  
   iter_init_from_char_offset (iter, tree, line, char_on_line);
 
   /* We might as well cache this, since we know it. */
@@ -4001,9 +4082,9 @@ _gtk_text_btree_get_iter_at_line_char (GtkTextBTree *tree,
 
 void
 _gtk_text_btree_get_iter_at_line_byte (GtkTextBTree   *tree,
-                                      GtkTextIter    *iter,
-                                      gint            line_number,
-                                      gint            byte_index)
+                                       GtkTextIter    *iter,
+                                       gint            line_number,
+                                       gint            byte_index)
 {
   GtkTextRealIter *real = (GtkTextRealIter*)iter;
   GtkTextLine *line;
@@ -4031,9 +4112,9 @@ _gtk_text_btree_get_iter_at_line_byte (GtkTextBTree   *tree,
 
 void
 _gtk_text_btree_get_iter_at_line      (GtkTextBTree   *tree,
-                                      GtkTextIter    *iter,
-                                      GtkTextLine    *line,
-                                      gint            byte_offset)
+                                       GtkTextIter    *iter,
+                                       GtkTextLine    *line,
+                                       gint            byte_offset)
 {
   g_return_if_fail (iter != NULL);
   g_return_if_fail (tree != NULL);
@@ -4253,8 +4334,8 @@ gtk_text_iter_check (const GtkTextIter *iter)
   if (real->line_byte_offset >= 0)
     {
       _gtk_text_line_byte_locate (real->line, real->line_byte_offset,
-                                 &byte_segment, &byte_any_segment,
-                                 &seg_byte_offset, &line_byte_offset);
+                                  &byte_segment, &byte_any_segment,
+                                  &seg_byte_offset, &line_byte_offset);
 
       if (line_byte_offset != real->line_byte_offset)
         g_error ("wrong byte offset was stored in iterator");
@@ -4284,8 +4365,8 @@ gtk_text_iter_check (const GtkTextIter *iter)
   if (real->line_char_offset >= 0)
     {
       _gtk_text_line_char_locate (real->line, real->line_char_offset,
-                                 &char_segment, &char_any_segment,
-                                 &seg_char_offset, &line_char_offset);
+                                  &char_segment, &char_any_segment,
+                                  &seg_char_offset, &line_char_offset);
 
       if (line_char_offset != real->line_char_offset)
         g_error ("wrong char offset was stored in iterator");
index 0f46d625a195e36be1ae321aeafc0b2e55261d24..17bd586b93a73058e437c44054becac54eab7a54 100644 (file)
@@ -133,6 +133,7 @@ gboolean gtk_text_iter_ends_line          (const GtkTextIter   *iter);
 gboolean gtk_text_iter_is_cursor_position (const GtkTextIter   *iter);
 
 gint     gtk_text_iter_get_chars_in_line (const GtkTextIter   *iter);
+gint     gtk_text_iter_get_bytes_in_line (const GtkTextIter   *iter);
 
 gboolean gtk_text_iter_get_attributes    (const GtkTextIter    *iter,
                                           GtkTextAttributes    *values);
index dad99f01ec598ab6aa5cee651b0469a498ac8dc8..47faaef1d4c2f8110b39a9970b02c1d18be40957 100644 (file)
@@ -1136,25 +1136,179 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
  * gtk_text_view_scroll_to_mark:
  * @text_view: a #GtkTextView
  * @mark: a #GtkTextMark
- * @mark_within_margin: a margin
+ * @within_margin: margin as a [0.0,0.5) fraction of screen size
+ * @use_align: whether to use alignment arguments (if %FALSE, just get the mark onscreen)
+ * @xalign: horizontal alignment of mark within visible area.
+ * @yalign: vertical alignment of mark within visible area
  *
- * Scrolls @text_view so that @mark is on the screen. If
- * @mark_within_margin is nonzero, the mark will be moved onscreen by
- * that many pixels. For example, if @mark_within_margin is 5, the
- * mark will be at least 5 pixels away from the edge of the screen,
- * if possible.
+ * Scrolls @text_view so that @mark is on the screen in the position
+ * indicated by @xalign and @yalign. An alignment of 0.0 indicates
+ * left or top, 1.0 indicates right or bottom, 0.5 means center. If @use_align
+ * is %FALSE, the text scrolls the minimal distance to get the mark onscreen,
+ * possibly not scrolling at all. The effective screen for purposes
+ * of this function is reduced by a margin of size @within_margin.
  *
- * Return value: TRUE if scrolling occurred
+ * Return value: %TRUE if scrolling occurred
  **/
 gboolean
 gtk_text_view_scroll_to_mark (GtkTextView *text_view,
                               GtkTextMark *mark,
-                              gint mark_within_margin)
+                              gdouble      within_margin,
+                              gboolean     use_align,
+                              gdouble      xalign,
+                              gdouble      yalign)
 {
-  g_return_val_if_fail (mark_within_margin >= 0, FALSE);
+  GtkTextIter iter;
+  GdkRectangle rect;
+  GdkRectangle screen;
+  gint screen_bottom;
+  gint screen_right;
+  gint scroll_dest;
+  GtkWidget *widget;
+  gboolean retval = FALSE;
+  gint scroll_inc;
+  gint screen_xoffset, screen_yoffset;
+  gint current_x_scroll, current_y_scroll;
+
+  g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+  g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
+  g_return_val_if_fail (within_margin >= 0.0 && within_margin < 0.5, FALSE);
+  g_return_val_if_fail (xalign >= 0.0 && xalign <= 1.0, FALSE);
+  g_return_val_if_fail (yalign >= 0.0 && yalign <= 1.0, FALSE);
+  
+  widget = GTK_WIDGET (text_view);
+
+  if (!GTK_WIDGET_MAPPED (widget))
+    {
+      g_warning ("FIXME need to implement scroll_to_mark for unmapped GtkTextView?");
+      return FALSE;
+    }
+
+  gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, mark);
 
-  return gtk_text_view_scroll_to_mark_adjusted (text_view, mark,
-                                                mark_within_margin, 1.0);
+  gtk_text_layout_get_iter_location (text_view->layout,
+                                     &iter,
+                                     &rect);
+
+  /* Be sure the scroll region is up-to-date */
+  gtk_text_view_scroll_calc_now (text_view);
+
+  current_x_scroll = text_view->xoffset;
+  current_y_scroll = text_view->yoffset;
+
+  screen.x = current_x_scroll;
+  screen.y = current_y_scroll;
+  screen.width = SCREEN_WIDTH (widget);
+  screen.height = SCREEN_HEIGHT (widget);
+  
+  screen_xoffset = screen.width * within_margin;
+  screen_yoffset = screen.height * within_margin;
+  
+  screen.x += screen_xoffset;
+  screen.y += screen_yoffset;
+  screen.width -= screen_xoffset * 2;
+  screen.height -= screen_yoffset * 2;
+
+  /* paranoia check */
+  if (screen.width < 1)
+    screen.width = 1;
+  if (screen.height < 1)
+    screen.height = 1;
+  
+  screen_right = screen.x + screen.width;
+  screen_bottom = screen.y + screen.height;
+  
+  /* The alignment affects the point in the target character that we
+   * choose to align. If we're doing right/bottom alignment, we align
+   * the right/bottom edge of the character the mark is at; if we're
+   * doing left/top we align the left/top edge of the character; if
+   * we're doing center alignment we align the center of the
+   * character.
+   */
+  
+  /* Vertical scroll */
+
+  scroll_inc = 0;
+  scroll_dest = current_y_scroll;
+  
+  if (use_align)
+    {      
+      scroll_dest = rect.y + (rect.height * yalign) - (screen.height * yalign);
+      
+      /* if scroll_dest < screen.y, we move a negative increment (up),
+       * else a positive increment (down)
+       */
+      scroll_inc = scroll_dest - screen.y + screen_yoffset;
+    }
+  else
+    {
+      /* move minimum to get onscreen */
+      if (rect.y < screen.y)
+        {
+          scroll_dest = rect.y;
+          scroll_inc = scroll_dest - screen.y - screen_yoffset;
+        }
+      else if ((rect.y + rect.height) > screen_bottom)
+        {
+          scroll_dest = rect.y + rect.height;
+          scroll_inc = scroll_dest - screen_bottom + screen_yoffset;
+        }
+    }  
+  
+  if (scroll_inc != 0)
+    {
+      set_adjustment_clamped (get_vadjustment (text_view),
+                              current_y_scroll + scroll_inc);
+      retval = TRUE;
+    }
+
+  /* Horizontal scroll */
+  
+  scroll_inc = 0;
+  scroll_dest = current_x_scroll;
+  
+  if (use_align)
+    {      
+      scroll_dest = rect.x + (rect.width * xalign) - (screen.width * xalign);
+
+      /* if scroll_dest < screen.y, we move a negative increment (left),
+       * else a positive increment (right)
+       */
+      scroll_inc = scroll_dest - screen.x + screen_xoffset;
+    }
+  else
+    {
+      /* move minimum to get onscreen */
+      if (rect.x < screen.x)
+        {
+          scroll_dest = rect.x;
+          scroll_inc = scroll_dest - screen.x - screen_xoffset;
+        }
+      else if ((rect.x + rect.width) > screen_right)
+        {
+          scroll_dest = rect.x + rect.width;
+          scroll_inc = scroll_dest - screen_right + screen_xoffset;
+        }
+    }
+  
+  if (scroll_inc != 0)
+    {
+      set_adjustment_clamped (get_hadjustment (text_view),
+                              current_x_scroll + scroll_inc);
+      retval = TRUE;
+    }
+
+  return retval;
+}
+
+gboolean
+gtk_text_view_scroll_mark_onscreen (GtkTextView *text_view,
+                                    GtkTextMark *mark)
+{
+  g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+  g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
+
+  return gtk_text_view_scroll_to_mark (text_view, mark, 0.0, FALSE, 0.0, 0.0);
 }
 
 static gboolean
@@ -1176,7 +1330,7 @@ clamp_iter_onscreen (GtkTextView *text_view, GtkTextIter *iter)
  * Moves a mark within the buffer so that it's
  * located within the currently-visible text area.
  *
- * Return value: %TRUE if scrolling occurred
+ * Return value: %TRUE if the mark moved (wasn't already onscreen)
  **/
 gboolean
 gtk_text_view_move_mark_onscreen (GtkTextView *text_view,
@@ -2533,7 +2687,7 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
       gtk_text_view_scroll_to_mark (text_view,
                                     gtk_text_buffer_get_mark (get_buffer (text_view),
                                                               "insert"),
-                                    0);
+                                    0.0, FALSE, 0.0, 0.0);
       retval = TRUE;
     }
   /* Pass through Tab as literal tab, unless Control is held down */
@@ -2541,10 +2695,9 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
     {
       gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\t", 1,
                                                     text_view->editable);
-      gtk_text_view_scroll_to_mark (text_view,
-                                    gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                              "insert"),
-                                    0);
+      gtk_text_view_scroll_mark_onscreen (text_view,
+                                          gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                    "insert"));
       retval = TRUE;
     }
   else
@@ -3190,9 +3343,9 @@ gtk_text_view_move_cursor (GtkTextView     *text_view,
       else
         gtk_text_buffer_place_cursor (get_buffer (text_view), &newplace);
 
-      gtk_text_view_scroll_to_mark (text_view,
-                                    gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                              "insert"), 0);
+      gtk_text_view_scroll_mark_onscreen (text_view,
+                                          gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                    "insert"));
 
       if (step == GTK_MOVEMENT_DISPLAY_LINES)
         {
@@ -3265,10 +3418,9 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
   /* Adjust to have the cursor _entirely_ onscreen, move_mark_onscreen
    * only guarantees 1 pixel onscreen.
    */
-  gtk_text_view_scroll_to_mark (text_view,
-                                gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                          "insert"),
-                                0);
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                "insert"));
 }
 
 static gboolean
@@ -3308,8 +3460,8 @@ gtk_text_view_insert_at_cursor (GtkTextView *text_view,
 
 static void
 gtk_text_view_delete_from_cursor (GtkTextView   *text_view,
-                                GtkDeleteType  type,
-                                gint           count)
+                                  GtkDeleteType  type,
+                                  gint           count)
 {
   GtkTextIter insert;
   GtkTextIter start;
@@ -3423,9 +3575,8 @@ gtk_text_view_delete_from_cursor (GtkTextView   *text_view,
 
       gtk_text_buffer_end_user_action (get_buffer (text_view));
       
-      gtk_text_view_scroll_to_mark (text_view,
-                                    gtk_text_buffer_get_mark (get_buffer (text_view), "insert"),
-                                    0);
+      gtk_text_view_scroll_mark_onscreen (text_view,
+                                          gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
     }
 }
 
@@ -3433,30 +3584,27 @@ static void
 gtk_text_view_cut_clipboard (GtkTextView *text_view)
 {
   gtk_text_buffer_cut_clipboard (get_buffer (text_view), text_view->editable);
-  gtk_text_view_scroll_to_mark (text_view,
-                                gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                          "insert"),
-                                0);
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                "insert"));
 }
 
 static void
 gtk_text_view_copy_clipboard (GtkTextView *text_view)
 {
   gtk_text_buffer_copy_clipboard (get_buffer (text_view));
-  gtk_text_view_scroll_to_mark (text_view,
-                                gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                          "insert"),
-                                0);
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                "insert"));
 }
 
 static void
 gtk_text_view_paste_clipboard (GtkTextView *text_view)
 {
   gtk_text_buffer_paste_clipboard (get_buffer (text_view), text_view->editable);
-  gtk_text_view_scroll_to_mark (text_view,
-                                gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                          "insert"),
-                                0);
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                "insert"));
 }
 
 static void
@@ -3486,86 +3634,31 @@ gtk_text_view_unselect (GtkTextView *text_view)
 }
 
 static gboolean
-move_insert_to_pointer_and_scroll (GtkTextView *text_view, gboolean partial_scroll)
+move_mark_to_pointer_and_scroll (GtkTextView *text_view,
+                                 const gchar *mark_name)
 {
   gint x, y;
   GdkModifierType state;
   GtkTextIter newplace;
-  gint adjust = 0;
-  gboolean in_threshold = FALSE;
 
   gdk_window_get_pointer (text_view->text_window->bin_window,
                           &x, &y, &state);
-
-  /* Adjust movement by how long we've been selecting, to
-     get an acceleration effect. The exact numbers are
-     pretty arbitrary. We have a threshold before we
-     start to accelerate. */
-  /* uncommenting this printf helps visualize how it works. */
-  /*   printf ("%d\n", text_view->scrolling_accel_factor); */
-
-  if (text_view->scrolling_accel_factor > 10)
-    adjust = (text_view->scrolling_accel_factor - 10) * 75;
-
-  if (y < 0) /* scrolling upward */
-    adjust = -adjust;
-
-  /* No adjust if the pointer has moved back inside the window for sure.
-     Also I'm adding a small threshold where no adjust is added,
-     in case you want to do a continuous slow scroll. */
-#define SLOW_SCROLL_TH 7
-  if (x >= (0 - SLOW_SCROLL_TH) &&
-      x < (SCREEN_WIDTH (text_view) + SLOW_SCROLL_TH) &&
-      y >= (0 - SLOW_SCROLL_TH) &&
-      y < (SCREEN_HEIGHT (text_view) + SLOW_SCROLL_TH))
-    {
-      adjust = 0;
-      in_threshold = TRUE;
-    }
-
+  
   gtk_text_layout_get_iter_at_pixel (text_view->layout,
                                      &newplace,
                                      x + text_view->xoffset,
-                                     y + text_view->yoffset + adjust);
+                                     y + text_view->yoffset);
 
   {
     gboolean scrolled = FALSE;
-    GtkTextMark *insert_mark =
-      gtk_text_buffer_get_mark (get_buffer (text_view), "insert");
+    GtkTextMark *mark =
+      gtk_text_buffer_get_mark (get_buffer (text_view), mark_name);
 
     gtk_text_buffer_move_mark (get_buffer (text_view),
-                               insert_mark,
+                               mark,
                                &newplace);
 
-    if (partial_scroll)
-      scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, insert_mark, 0, 0.7);
-    else
-      scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, insert_mark, 0, 1.0);
-
-    if (scrolled)
-      {
-        /* We want to avoid rapid jump to super-accelerated when you
-           leave the slow scroll threshold after scrolling for a
-           while. So we slowly decrease accel when scrolling inside
-           the threshold.
-        */
-        if (in_threshold)
-          {
-            if (text_view->scrolling_accel_factor > 1)
-              text_view->scrolling_accel_factor -= 2;
-          }
-        else
-          text_view->scrolling_accel_factor += 1;
-      }
-    else
-      {
-        /* If we don't scroll we're probably inside the window, but
-           potentially just a bit outside. We decrease acceleration
-           while the user is fooling around inside the window.
-           Acceleration decreases faster than it increases. */
-        if (text_view->scrolling_accel_factor > 4)
-          text_view->scrolling_accel_factor -= 5;
-      }
+    scrolled = gtk_text_view_scroll_mark_onscreen (text_view, mark);
 
     return scrolled;
   }
@@ -3578,32 +3671,57 @@ selection_scan_timeout (gpointer data)
 
   text_view = GTK_TEXT_VIEW (data);
 
-  if (move_insert_to_pointer_and_scroll (text_view, TRUE))
-    {
-      return TRUE; /* remain installed. */
-    }
-  else
-    {
-      text_view->selection_drag_scan_timeout = 0;
-      return FALSE; /* remove ourselves */
-    }
+  move_mark_to_pointer_and_scroll (text_view, "insert");
+
+  return TRUE; /* remain installed. */
+}
+
+#define DND_SCROLL_MARGIN 0.20
+
+static gint
+drag_scan_timeout (gpointer data)
+{
+  GtkTextView *text_view;
+  gint x, y;
+  GdkModifierType state;
+  GtkTextIter newplace;
+  
+  text_view = GTK_TEXT_VIEW (data);
+
+  gdk_window_get_pointer (text_view->text_window->bin_window,
+                          &x, &y, &state);
+  
+  gtk_text_layout_get_iter_at_pixel (text_view->layout,
+                                     &newplace,
+                                     x + text_view->xoffset,
+                                     y + text_view->yoffset);
+  
+  gtk_text_buffer_move_mark (get_buffer (text_view),
+                             text_view->dnd_mark,
+                             &newplace);
+  
+  gtk_text_view_scroll_to_mark (text_view,
+                                text_view->dnd_mark,
+                                DND_SCROLL_MARGIN, FALSE, 0.0, 0.0);
+
+  return TRUE;
 }
 
 static gint
 selection_motion_event_handler (GtkTextView *text_view, GdkEventMotion *event, gpointer data)
 {
-  if (move_insert_to_pointer_and_scroll (text_view, TRUE))
-    {
-      /* If we had to scroll offscreen, insert a timeout to do so
-         again. Note that in the timeout, even if the mouse doesn't
-         move, due to this scroll xoffset/yoffset will have changed
-         and we'll need to scroll again. */
-      if (text_view->selection_drag_scan_timeout != 0) /* reset on every motion event */
-        gtk_timeout_remove (text_view->selection_drag_scan_timeout);
+  move_mark_to_pointer_and_scroll (text_view, "insert");
 
-      text_view->selection_drag_scan_timeout =
-        gtk_timeout_add (50, selection_scan_timeout, text_view);
-    }
+  /* If we had to scroll offscreen, insert a timeout to do so
+   * again. Note that in the timeout, even if the mouse doesn't
+   * move, due to this scroll xoffset/yoffset will have changed
+   * and we'll need to scroll again.
+   */
+  if (text_view->scroll_timeout != 0) /* reset on every motion event */
+    gtk_timeout_remove (text_view->scroll_timeout);
+  
+  text_view->scroll_timeout =
+    gtk_timeout_add (50, selection_scan_timeout, text_view);
 
   return TRUE;
 }
@@ -3619,8 +3737,6 @@ gtk_text_view_start_selection_drag (GtkTextView       *text_view,
 
   gtk_grab_add (GTK_WIDGET (text_view));
 
-  text_view->scrolling_accel_factor = 0;
-
   newplace = *iter;
 
   gtk_text_buffer_place_cursor (get_buffer (text_view), &newplace);
@@ -3641,16 +3757,14 @@ gtk_text_view_end_selection_drag (GtkTextView *text_view, GdkEventButton *event)
   gtk_signal_disconnect (GTK_OBJECT (text_view), text_view->selection_drag_handler);
   text_view->selection_drag_handler = 0;
 
-  text_view->scrolling_accel_factor = 0;
-
-  if (text_view->selection_drag_scan_timeout != 0)
+  if (text_view->scroll_timeout != 0)
     {
-      gtk_timeout_remove (text_view->selection_drag_scan_timeout);
-      text_view->selection_drag_scan_timeout = 0;
+      gtk_timeout_remove (text_view->scroll_timeout);
+      text_view->scroll_timeout = 0;
     }
 
   /* one last update to current position */
-  move_insert_to_pointer_and_scroll (text_view, FALSE);
+  move_mark_to_pointer_and_scroll (text_view, "insert");
 
   gtk_grab_remove (GTK_WIDGET (text_view));
 
@@ -3869,7 +3983,7 @@ gtk_text_view_reset_im_context (GtkTextView *text_view)
 {
   if (text_view->need_im_reset)
     {
-      text_view->need_im_reset = 0;
+      text_view->need_im_reset = FALSE;
       gtk_im_context_reset (text_view->im_context);
     }
 }
@@ -3921,8 +4035,14 @@ gtk_text_view_drag_end (GtkWidget        *widget,
   GtkTextView *text_view;
 
   text_view = GTK_TEXT_VIEW (widget);
-
+  
   gtk_text_mark_set_visible (text_view->dnd_mark, FALSE);
+
+  if (text_view->scroll_timeout != 0)
+    {
+      gtk_timeout_remove (text_view->scroll_timeout);
+      text_view->scroll_timeout = 0;
+    }
 }
 
 static void
@@ -3986,8 +4106,16 @@ gtk_text_view_drag_leave (GtkWidget        *widget,
                           GdkDragContext   *context,
                           guint             time)
 {
+  GtkTextView *text_view;
+
+  text_view = GTK_TEXT_VIEW (widget);
 
+  gtk_text_mark_set_visible (text_view->dnd_mark, FALSE);
+  
+  if (text_view->scroll_timeout != 0)
+    gtk_timeout_remove (text_view->scroll_timeout);
 
+  text_view->scroll_timeout = 0;
 }
 
 static gboolean
@@ -4003,11 +4131,12 @@ gtk_text_view_drag_motion (GtkWidget        *widget,
   GtkTextIter end;
   GdkRectangle target_rect;
   gint bx, by;
+  gboolean scrolled;
   
   text_view = GTK_TEXT_VIEW (widget);
 
   target_rect = text_view->text_window->allocation;
-
+  
   if (x < target_rect.x ||
       y < target_rect.y ||
       x > (target_rect.x + target_rect.width) ||
@@ -4065,25 +4194,19 @@ gtk_text_view_drag_motion (GtkWidget        *widget,
     }
 
   gtk_text_buffer_move_mark (get_buffer (text_view),
-                             gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                       "gtk_drag_target"),
+                             text_view->dnd_mark,
                              &newplace);
 
-  {
-    /* The effect of this is that the text scrolls if you're near
-       the edge. We have to scroll whether or not we're inside
-       the selection. */
-    gint margin;
-
-    margin = MIN (SCREEN_WIDTH (widget), SCREEN_HEIGHT (widget));
-    margin /= 5;
-
-    gtk_text_view_scroll_to_mark_adjusted (text_view,
-                                           gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                                     "gtk_drag_target"),
-                                           margin, 1.0);
-  }
-
+  scrolled = gtk_text_view_scroll_to_mark (text_view,
+                                           text_view->dnd_mark,
+                                           DND_SCROLL_MARGIN, FALSE, 0.0, 0.0);
+  
+  if (text_view->scroll_timeout != 0) /* reset on every motion event */
+    gtk_timeout_remove (text_view->scroll_timeout);
+      
+  text_view->scroll_timeout =
+    gtk_timeout_add (50, drag_scan_timeout, text_view);
+  
   return TRUE;
 }
 
@@ -4360,10 +4483,9 @@ gtk_text_view_commit_handler (GtkIMContext  *context,
 
   gtk_text_buffer_end_user_action (get_buffer (text_view));
   
-  gtk_text_view_scroll_to_mark (text_view,
-                                gtk_text_buffer_get_mark (get_buffer (text_view),
-                                                          "insert"),
-                                0);
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_mark (get_buffer (text_view),
+                                                                "insert"));
 }
 
 static void
index edcc8f2870d4e7f1d5a3c56469143012642756a4..26938160566df904538d1223520cad63b3c08a6f 100644 (file)
@@ -67,8 +67,7 @@ struct _GtkTextView
   GtkTextBuffer *buffer;
 
   guint selection_drag_handler;
-  guint selection_drag_scan_timeout;
-  gint scrolling_accel_factor;
+  guint scroll_timeout;
 
   /* Default style settings */
   gint pixels_above_lines;
@@ -175,7 +174,12 @@ void           gtk_text_view_set_buffer            (GtkTextView   *text_view,
 GtkTextBuffer *gtk_text_view_get_buffer            (GtkTextView   *text_view);
 gboolean       gtk_text_view_scroll_to_mark        (GtkTextView   *text_view,
                                                     GtkTextMark   *mark,
-                                                    gint           mark_within_margin);
+                                                    gdouble        within_margin,
+                                                    gboolean       use_align,
+                                                    gdouble        xalign,
+                                                    gdouble        yalign);
+gboolean       gtk_text_view_scroll_mark_onscreen  (GtkTextView   *text_view,
+                                                    GtkTextMark   *mark);
 gboolean       gtk_text_view_move_mark_onscreen    (GtkTextView   *text_view,
                                                     GtkTextMark   *mark);
 gboolean       gtk_text_view_place_cursor_onscreen (GtkTextView   *text_view);
index f41e2f5a2fee11c029050b3ba5f9efb7840900a6..b14ce64eef0713073c2f5ff7b675f4c33a6bad78 100644 (file)
@@ -602,7 +602,7 @@ fill_buffer (GtkTextBuffer *buffer)
 
   color.blue = color.green = 0;
   color.red = 0xffff;
-  g_object_set (GTK_OBJECT (tag),
+  g_object_set (G_OBJECT (tag),
                 "rise", -4,
                 "foreground_gdk", &color,
                 NULL);
index f41e2f5a2fee11c029050b3ba5f9efb7840900a6..b14ce64eef0713073c2f5ff7b675f4c33a6bad78 100644 (file)
@@ -602,7 +602,7 @@ fill_buffer (GtkTextBuffer *buffer)
 
   color.blue = color.green = 0;
   color.red = 0xffff;
-  g_object_set (GTK_OBJECT (tag),
+  g_object_set (G_OBJECT (tag),
                 "rise", -4,
                 "foreground_gdk", &color,
                 NULL);